#!/usr/bin/env python
# encoding: utf-8


"""
@file: sanjiaoxing_bianzuizhi.py
@time: 2016/12/14 下午3:23
"""
# 边的四则运算的最值--题型
from mathsolver.functions.base import *
from sympy import pi, sin, cos, simplify, sqrt, expand, collect, expand_trig, cancel
import sanjiao_utils
import triangle_constant as t_const


# 14-1 已知角A的值（或者角的三角函数值cosA=n），对边的长度a=m，求b^2+c^2的最大值
class BianZuiZhi01(BaseFunction):
    def solver(self, *args):
        eqs = args[0].sympify()
        if len(eqs) != 2:
            raise Exception('Match Type Error')
        eq1, eq2 = eqs
        f = args[1].sympify()
        f1 = sanjiao_utils.radianed((eq1[0] - eq1[1]).subs(t_const.LINE_SUBS))
        f2 = sanjiao_utils.radianed((eq2[0] - eq2[1]).subs(t_const.LINE_SUBS))
        symbs1 = list(f1.free_symbols)
        symbs2 = list(f2.free_symbols)
        if not (len(symbs1) == 1 and len(symbs2) == 1):
            raise Exception('Match Type Error')
        if str(symbs1[0]).lower() != str(symbs2[0]).lower():
            raise Exception('Type Match Error')
        if symbs1[0] in [sympify('a'), sympify('b'), sympify('c')]:
            side = symbs1[0]
            side_value = solve(f1)[0]
            angle = symbs2[0]
            angle_value = solve(f2)[0]
        else:
            side = symbs2[0]
            side_value = solve(f2)[0]
            angle = symbs1[0]
            angle_value = solve(f1)[0]
        other_side1, other_side2 = list(t_const.SIDES - FiniteSet(side))
        tmp_f1_l = side ** 2
        tmp_f1_r = other_side1 ** 2 + other_side2 ** 2 - 2 * other_side1 * other_side2 * cos(angle)
        self.steps.append(['利用余弦定理得：%s = %s' % (new_latex(tmp_f1_l), new_latex(tmp_f1_r)), ''])
        tmp_f2_l = tmp_f1_l.subs(side, side_value)
        tmp_f2_r = tmp_f1_r.subs(angle, angle_value)
        self.steps.append(['即：%s = %s ' % (new_latex(tmp_f2_l), new_latex(tmp_f2_r)), ''])
        tmp_f3_l = f
        tmp_f3_r = solve(tmp_f2_l - tmp_f2_r, f)[0]
        self.steps.append(['%s = %s' % (new_latex(tmp_f3_l), new_latex(tmp_f3_r)), ''])
        self.steps.append(
            ['%s <= %s' % (new_latex(2 * other_side1 * other_side2), new_latex(other_side1 ** 2 + other_side2 ** 2)), ''])
        tmp_f4_r = tmp_f3_r.subs(2 * other_side1 * other_side2, other_side1 ** 2 + other_side2 ** 2)
        self.steps.append(['%s = %s <= %s' % (new_latex(tmp_f3_l), new_latex(tmp_f3_r), new_latex(tmp_f4_r)), ''])
        last_f = (f - tmp_f4_r).subs(other_side1 ** 2, sympify('t') - other_side2 ** 2)
        max_value = solve(last_f, 't')[0]
        self.steps.append(['整理得: %s <= %s' % (new_latex(f), new_latex(max_value)), ''])
        self.steps.append(['故答案为：' + new_latex(max_value), ''])
        self.output.append(BaseNumber(max_value))
        return self


# 14-2.已知角A的值（或者角的三角函数值sinA=n），对边的长度a=m，求b+c的最大值
class BianZuiZhi02(BaseFunction):
    @staticmethod
    def simp_f(f):
        f = sympify(f)
        s1, s2 = sorted(f.free_symbols, key=str)
        tmp_f = (s1 + s2) ** 2
        fill_mons = collect(expand(f) - expand(tmp_f), s1 * s2)
        last_f = tmp_f + fill_mons
        return last_f

    def solver(self, *args):
        eqs = args[0].sympify()
        if len(eqs) != 2:
            raise Exception('Match Type Error')
        eq1, eq2 = eqs
        f = args[1].sympify()
        f1 = sanjiao_utils.radianed((eq1[0] - eq1[1]).subs(t_const.LINE_SUBS))
        f2 = sanjiao_utils.radianed((eq2[0] - eq2[1]).subs(t_const.LINE_SUBS))
        symbs1 = list(f1.free_symbols)
        symbs2 = list(f2.free_symbols)
        if not (len(symbs1) == 1 and len(symbs2) == 1):
            raise Exception('Match Type Error')
        if str(symbs1[0]).lower() != str(symbs2[0]).lower():
            raise Exception('Type Match Error')
        if symbs1[0] in [sympify('a'), sympify('b'), sympify('c')]:
            side = symbs1[0]
            side_value = solve(f1)[0]
            angle_value = solve(f2)[0]
        else:
            side = symbs2[0]
            side_value = solve(f2)[0]
            angle_value = solve(f1)[0]
        other_side1, other_side2 = list(t_const.SIDES - FiniteSet(side))
        self.steps.append(['由余弦定理得:', ''])
        tmp_f = other_side1 ** 2 + other_side2 ** 2 - 2 * other_side1 * other_side2 * cos(angle_value)
        sim_tmp_f = BianZuiZhi02.simp_f(tmp_f)
        self.steps.append([new_latex(side ** 2) + '=' + new_latex(tmp_f), ''])
        self.steps.append(['=' + new_latex(sim_tmp_f), ''])
        coef = sim_tmp_f.coeff(other_side1 * other_side2)
        tmp_f2 = (other_side1 + other_side2) ** 2 + sympify('1') / 4 * coef * (other_side1 + other_side2) ** 2
        self.steps.append(['>=' + new_latex(tmp_f2), ''])
        tmp_f2 = collect(tmp_f2, (other_side1 + other_side2) ** 2)
        self.steps.append(['=' + new_latex(tmp_f2), ''])
        coef2 = tmp_f2.coeff((other_side1 + other_side2) ** 2)
        op_value = simplify(side_value ** 2 / coef2)
        self.steps.append(['即 ' + new_latex((other_side1 + other_side2) ** 2), '<=' + new_latex(op_value)])
        self.steps.append(['当且仅当 %s=%s' % (new_latex(other_side1), new_latex(other_side2)), '时，等号成立。'])
        self.steps.append(['\\therefore %s 最大值为' % new_latex(f), new_latex(sqrt(op_value))])
        self.output.append(BaseNumber(sqrt(op_value)))
        return self


# 3.已知角A的值（或者角的三角函数值sinA=n），对边的长度a=m，求kb+wc的最大值
class BianZuiZhi03(BaseFunction):
    def solver(self, *args):
        eqs = args[0].sympify()
        if len(eqs) != 2:
            raise Exception('Match Type Error')
        eq1, eq2 = eqs
        f1 = sanjiao_utils.radianed((eq1[0] - eq1[1]).subs(t_const.LINE_SUBS))
        f2 = sanjiao_utils.radianed((eq2[0] - eq2[1]).subs(t_const.LINE_SUBS))
        symbs1 = list(f1.free_symbols)
        symbs2 = list(f2.free_symbols)
        if not (len(symbs1) == 1 and len(symbs2) == 1):
            raise Exception('Match Type Error')
        if str(symbs1[0]).lower() != str(symbs2[0]).lower():
            raise Exception('Match Type Error')
        src_f = args[1].sympify()
        f = args[1].sympify().subs(t_const.LINE_SUBS)
        if symbs1[0] in [sympify('a'), sympify('b'), sympify('c')]:
            side = symbs1[0]
            side_value = solve(f1)[0]
            angle = symbs2[0]
            angle_value = solve(f2)[0]
        else:
            side = symbs2[0]
            side_value = solve(f2)[0]
            angle = symbs1[0]
            angle_value = solve(f1)[0]
        other_side1, other_side2 = list(t_const.SIDES - FiniteSet(side))
        other_angle1 = sympify(str(other_side1).upper())
        other_angle2 = sympify(str(other_side2).upper())
        self.steps.append(['\\because %s=%s ，' % (new_latex(angle), new_latex(angle_value)),
                           '\\therefore ' + new_latex(other_side1 + other_side2) + '=' + new_latex(pi - angle_value)])
        ratio = side_value / sin(angle_value)
        self.steps.append(['由正弦定理，得' + new_latex(side / sin(angle)) + '=' + new_latex(
            other_side1 / sin(other_angle1)) + '=' + new_latex(other_side2 / sin(other_angle2)),
                           '=' + new_latex(ratio)])
        other_side1_f_sub = ratio * sin(other_angle1)
        other_side2_f_sub = ratio * sin(other_angle2)
        self.steps.append(['\\therefore %s=%s' % (new_latex(other_side1), new_latex(other_side1_f_sub)),
                           '，%s=%s' % (new_latex(other_side2), new_latex(other_side2_f_sub))])
        f_subs = f.subs(((other_side1, other_side1_f_sub), (other_side2, other_side2_f_sub)))
        f_subs_2 = expand_trig(f_subs.subs(other_angle2, pi - angle_value - other_angle1))
        self.steps.append(['\\therefore ' + new_latex(src_f) + '=' + new_latex(f_subs), ''])
        self.steps.append(['=' + new_latex(f_subs_2), ''])
        f_simp, tan_theta = sanjiao_utils.aux_ang_f(f_subs_2)
        coef = sanjiao_utils.trig_coeff(f_simp)
        self.steps.append(['=' + new_latex(f_simp), '，（其中\tan \theta =%s）' % new_latex(tan_theta)])
        self.steps.append(['所以%s的最大值为%s' % (new_latex(src_f), new_latex(coef)), ''])
        self.output.append(BaseNumber(coef))
        return self


# 014-4.已知角A的值（或者角的三角函数值sinA=n），求（kb+wc）/ta的最大值
class BianZuiZhi04(BaseFunction):
    def solver(self, *args):
        eq = args[0]
        l_expr, r_expr = eq.sympify()
        eq_f = sanjiao_utils.radianed((l_expr - r_expr).subs(t_const.LINE_SUBS))
        symbs = list(eq_f.free_symbols)
        if len(symbs) != 1 or symbs[0] not in t_const.ANGLES:
            raise Exception('Match Type Error')
        src_f = args[1].sympify()
        f = args[1].sympify().subs(t_const.LINE_SUBS)
        angle = symbs[0]
        angle_value = solve(eq_f)[0]
        other_angle1, other_angle2 = t_const.ANGLES - FiniteSet(angle)
        self.steps.append(
            ['\\because ' + eq.printing(),
             '，\\therefore ' + new_latex(other_angle1 + other_angle2) + '=' + new_latex(pi - angle_value)])
        self.steps.append(['则%s=%s' % (new_latex(other_angle1), new_latex(pi - angle_value - other_angle2)),
                           '且0<%s<%s' % (new_latex(other_angle1), new_latex(pi - angle_value))])
        f_subs = f.subs(
            ((str(angle).lower(), sin(angle)), (str(other_angle1).lower(), sin(other_angle1)),
             (str(other_angle2).lower(), sin(other_angle2))))
        f_subs2 = f_subs.subs(sin(angle), sin(angle_value))
        self.steps.append(['由正弦定理得, %s=%s' % (new_latex(src_f), new_latex(f_subs)), '=' + new_latex(f_subs2)])
        f_subs3 = f_subs2.subs(other_angle2, pi - angle_value - other_angle1)
        f_subs4 = expand_trig(f_subs3)
        f_subs5, tan_theta = sanjiao_utils.aux_ang_f(f_subs4)
        self.steps.append(['=' + new_latex(f_subs3),
                           '=' + new_latex(f_subs4) + '=' + new_latex(f_subs5) + '，（其中\\tan \\theta =%s）' % new_latex(tan_theta)])
        coef = sanjiao_utils.trig_coeff(f_subs5)
        sin_arg = (f_subs5 / coef).args[0]
        max_value = coef * sin(pi - angle_value)
        self.steps.append(['\\therefore 当 %s=%s时，%s最大值为' % (new_latex(sin_arg), new_latex(pi - angle_value), new_latex(f_subs5)),
                           new_latex(max_value)])
        self.steps.append(['即 %s 的最大值为%s' % (new_latex(src_f), new_latex(max_value)), ''])
        self.output.append(BaseNumber(max_value))
        return self


# 5.已边a上的高h=ma，求b/c+c/b的最大值
class BianZuiZhi05(BaseFunction):
    def solver(self, *args):
        eq = args[0]
        l_expr, r_expr = eq.sympify()
        eq_f = l_expr - r_expr
        side = list(filter(lambda symb: sympify(str(symb).lower()) in list(t_const.SIDES), list(eq_f.free_symbols)))[0]
        side_value = solve(eq_f, side)[0]
        h_symbol = list(FiniteSet(*eq_f.free_symbols) - FiniteSet(side))[0]
        h_symbol_value = solve(eq_f, h_symbol)[0]
        coef = h_symbol_value.coeff(side)
        angle = sympify(str(side).upper())
        src_f = args[1].sympify()
        f = src_f.subs(t_const.LINE_SUBS)
        f = cancel(f)
        f_symbs = map(sympify, sorted(map(str, f.free_symbols)))
        f_symb1, f_symb2 = f_symbs
        f1_l = sympify('1') / 2 * side * h_symbol
        f1_r = sympify('1') / 2 * f_symb1 * f_symb2 * sin(angle)
        self.steps.append(['\\because {S_{\\Delta ABC}} = ' + new_latex(f1_l) + ' = ' + new_latex(f1_r), ''])
        f2_l = f_symb1 * f_symb2
        f2_r = solve(f1_l - f1_r, f2_l)[0]
        self.steps.append(
            ['\\therefore %s = %s' % (new_latex(f2_l), new_latex(f2_r)), '又 %s= %s' % (new_latex(side), new_latex(side_value))])
        f3_l = f_symb1 ** 2 + f_symb2 ** 2
        f3_r = side ** 2 + 2 * f_symb1 * f_symb2 * cos(angle)
        self.steps.append(['\\therefore 由余弦定理 %s = %s' % (new_latex(f3_l), new_latex(f3_r)), ''])
        f2 = f.subs(f3_l, f3_r)
        f3 = simplify(f2.subs(f2_l, f2_r))
        self.steps.append(['又 %s = %s' % (new_latex(src_f), new_latex(f)), ' = ' + new_latex(f2) + '=' + new_latex(f3)])
        f4 = f3.subs(h_symbol, h_symbol_value)
        f5, tan_v = sanjiao_utils.aux_ang_f(f4)
        self.steps.append([' = ' + new_latex(f4), new_latex(f5) + '(\\tan \\theta  = %s)' % new_latex(tan_v)])
        max_value = sanjiao_utils.trig_coeff(f5)
        self.steps.append(['\\therefore %s 的最大值是 %s' % (new_latex(src_f), new_latex(max_value)), ''])
        self.steps.append(['故答案为：' + new_latex(max_value), ''])
        self.output.append(BaseNumber(max_value))
        return self


# 6.已边a上的高h=ma，求b/c+c/b+a^2/bc的最大值
class BianZuiZhi06(BaseFunction):
    def solver(self, *args):
        eq = args[0]
        l_expr, r_expr = eq.sympify()
        eq_f = l_expr - r_expr
        side = list(filter(lambda symb: sympify(str(symb).lower()) in list(t_const.SIDES), list(eq_f.free_symbols)))[0]
        h_symbol = list(FiniteSet(*eq_f.free_symbols) - FiniteSet(side))[0]
        h_symbol_value = solve(eq_f, h_symbol)[0]
        angle = sympify(str(side).upper())
        src_f = args[1].sympify()
        f = src_f.subs(t_const.LINE_SUBS)
        f = cancel(f)
        f_symbs = FiniteSet(*map(sympify, sorted(map(str, f.free_symbols))))
        if f_symbs != t_const.SIDES:
            raise Exception('Type Match Error')
        f_symb1, f_symb2 = f_symbs - FiniteSet(side)
        self.steps.append(['由题意可知 ' + eq.printing(), ''])
        f1_l = sympify('1') / 2 * h_symbol_value * side
        f1_r = sympify('1') / 2 * f_symb1 * f_symb2 * sin(angle)
        side_quad = solve(f1_l - f1_r, side ** 2)[0]
        self.steps.append(
            ['\\therefore %s = %s' % (new_latex(f1_l), new_latex(f1_r)), '即 %s=%s' % (new_latex(side ** 2), new_latex(side_quad))])
        f2 = f.subs(f_symb1 ** 2 + f_symb2 ** 2, 2 * f_symb1 * f_symb2 * cos(angle) + side ** 2)
        f3 = f2.subs(side ** 2, side_quad)
        self.steps.append(['\\because ' + new_latex(src_f) + '=' + new_latex(f) + '=' + new_latex(f2), ''])
        f4 = simplify(f3)
        f5, tan_v = sanjiao_utils.aux_ang_f(f4)
        self.steps.append(['\\therefore ' + new_latex(src_f) + '=' + new_latex(f3),
                           '=' + new_latex(f4) + '=' + new_latex(f5) + ' 其中(\\tan \\theta  = %s)' % new_latex(tan_v)])
        max_value = sanjiao_utils.trig_coeff(f5)
        self.steps.append(['\\therefore %s 的最大值为%s' % (new_latex(src_f), new_latex(max_value)), ''])
        self.output.append(BaseNumber(max_value))
        return self


if __name__ == '__main__':
    pass
